﻿#pragma once

// 平台和编译器
//////////////////////////////////////////////////////////////////////////
#if defined(_WIN64) || defined(__WIN64__) || defined(WIN64)
#	define XYNET_PLATFORM_WIN64
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#	define XYNET_PLATFORM_WIN32
#elif defined(__ANDROID__) || defined(__ANDROID_API__)
#   define XYNET_PLATFORM_ANDROID
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#   define XYNET_PLATFORM_APPLE
#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
#	define XYNET_PLATFORM_LINUX
#endif

#if defined(XYNET_PLATFORM_WIN64) || defined(XYNET_PLATFORM_WIN32)
#	define XYNET_PLATFORM_WINDOWS
#endif

#if defined(_MSC_VER)
#   define XYNET_COMPILER_MSVC
#elif defined(__GNUC__)
#   define XYNET_COMPILER_GCC
#endif

// MSVC设置
#ifdef XYNET_COMPILER_MSVC
// 屏蔽警告
#   pragma warning(disable:4191)
#   pragma warning(disable:4251)
#   pragma warning(disable:4275)
#   pragma warning(disable:4297)
#   pragma warning(disable:4503)
#   pragma warning(disable:4661)
#   pragma warning(disable:4819)
#   pragma warning(disable:4996)

#	pragma warning(error:4390)

// 设置执行字符集
#   pragma execution_character_set("utf-8")

// 控制台设置
#   if !defined(XYNET_HIDE_CONSOLE)
#       pragma comment(linker, "/subsystem:console")
#	else
#       pragma comment(linker, "/subsystem:windows /entry:mainCRTStartup")
#   endif

// 去除一些不需要的windows API
#   define WIN32_LEAN_AND_MEAN
#   define NOMINMAX

//// 开启内存泄漏检查
//#if defined(XYNET_PLATFORM_WIN32) && defined(_DEBUG)
//#   include <vld/vld.h>
//#endif

#	if defined(_MSC_VER) && !defined(_WIN32_WINNT)
#		define _WIN32_WINNT BOOST_WINAPI_VERSION_WIN6
#	endif

#else

#	if !defined(NDEBUG) && !defined(_DEBUG)
#		define _DEBUG
#	endif

#endif

// 定义导出宏
//////////////////////////////////////////////////////////////////////////
//#define XYNET_STATIC
#if defined(XYNET_PLATFORM_WINDOWS) && !defined(XYNET_STATIC)
#	ifdef XYNET_EXPORTS
#		define XYNET_API __declspec(dllexport)
#	else
#		define XYNET_API __declspec(dllimport)
#	endif
#else
#	define XYNET_API
#endif

// 定义基本类型
//////////////////////////////////////////////////////////////////////////
#include <cstdint>

typedef unsigned char byte;

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;

typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;

#ifndef XYNET_DOUBLE_PRECISION
typedef float real;
#else
typedef double real;
#endif

// 定义常用类型和函数
//////////////////////////////////////////////////////////////////////////
#include <functional>
#include <iostream>
#include <memory>
#include <string>

#ifndef XYNET_PLATFORM_WINDOWS
namespace std
{
	template<class _Ty, class... _Types>
	inline typename enable_if<!is_array<_Ty>::value, unique_ptr<_Ty> >::type
		make_unique(_Types&&... _Args)
	{
		return (unique_ptr<_Ty>(new _Ty(::std::forward<_Types>(_Args)...)));
	}
}
#endif

using std::cin;
using std::cout;
using std::cerr;
using std::endl;

using std::unique_ptr;
using std::make_unique;
using std::shared_ptr;
using std::weak_ptr;
using std::make_shared;
using std::enable_shared_from_this;
using std::const_pointer_cast;
using std::static_pointer_cast;
using std::dynamic_pointer_cast;

using std::string;
using std::wstring;

using std::exception;
using std::locale;

// android必须用std版本的bind function
using std::bind;
using std::function;

// 定义常用容器
//////////////////////////////////////////////////////////////////////////
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <tuple>

using std::pair;
using std::make_pair;

using std::stack;
using std::queue;
using std::vector;
using std::deque;
using std::list;

using std::set;
using std::map;
using std::multiset;
using std::multimap;
using std::unordered_set;
using std::unordered_map;
using std::unordered_multiset;
using std::unordered_multimap;

using std::tuple;

typedef string Bytes;

// 定义boost
//////////////////////////////////////////////////////////////////////////
#include <boost/atomic.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/thread.hpp>

using boost::lexical_cast;
using boost::numeric_cast;

using boost::noncopyable;

namespace filesystem = boost::filesystem;

namespace chrono = boost::chrono;

namespace this_thread = boost::this_thread;
using boost::thread;
using boost::mutex;
using boost::shared_mutex;
using boost::unique_lock;
using boost::shared_lock;
using boost::upgrade_lock;
using boost::upgrade_to_unique_lock;
using boost::atomic;

using boost::any;
using boost::any_cast;

#define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)

#define XYNET_STRINGIZE(X) #X